package com.wolfcode.flow.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.wolfcode.common.annotation.Excel;
import com.wolfcode.common.utils.DateUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wolfcode.flow.mapper.BusBpmnInfoMapper;
import com.wolfcode.flow.domain.BusBpmnInfo;
import com.wolfcode.flow.service.IBusBpmnInfoService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

/**
 * 流程定义明细Service业务层处理
 * 
 * @author wolfcode
 * @date 2022-11-28
 */
@Service
public class BusBpmnInfoServiceImpl implements IBusBpmnInfoService 
{
    @Autowired
    private BusBpmnInfoMapper busBpmnInfoMapper;
    @Autowired
    private RepositoryService repositoryService;

    /**
     * 查询流程定义明细
     * 
     * @param id 流程定义明细主键
     * @return 流程定义明细
     */
    @Override
    public BusBpmnInfo selectBusBpmnInfoById(Long id)
    {
        return busBpmnInfoMapper.selectBusBpmnInfoById(id);
    }

    /**
     * 查询流程定义明细列表
     * 
     * @param busBpmnInfo 流程定义明细
     * @return 流程定义明细
     */
    @Override
    public List<BusBpmnInfo> selectBusBpmnInfoList(BusBpmnInfo busBpmnInfo)
    {
        return busBpmnInfoMapper.selectBusBpmnInfoList(busBpmnInfo);
    }

    /**
     * 新增流程定义明细
     * 
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int insertBusBpmnInfo(BusBpmnInfo busBpmnInfo)
    {
        return busBpmnInfoMapper.insertBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 修改流程定义明细
     * 
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int updateBusBpmnInfo(BusBpmnInfo busBpmnInfo)
    {
        return busBpmnInfoMapper.updateBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 批量删除流程定义明细
     * 
     * @param ids 需要删除的流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBusBpmnInfoByIds(Long[] ids)
    {
        return busBpmnInfoMapper.deleteBusBpmnInfoByIds(ids);
    }

    /**
     * 删除流程定义明细信息
     * 
     * @param id 流程定义明细主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteBusBpmnInfoById(Long id)
    {
        Assert.notNull(id,"非法参数");
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBusBpmnInfoById(id);
        Assert.notNull(busBpmnInfo,"流程定义文件不存在");
        // TODO：这一期不考虑，流程实例是否启动，是否要挂起，
        // TODO: 目前这一期慎用
        //流程定义信息表删除
        //TODO:权限：超管才能操作
        //级联删除
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(busBpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(busBpmnInfo.getVersion().intValue())
                .singleResult();
        Assert.notNull(processDefinition,"流程定义文件不存在");
        repositoryService.deleteDeployment(processDefinition.getDeploymentId(),true);
        //删除部署的流程
        return busBpmnInfoMapper.deleteBusBpmnInfoById(id);
    }

    /**
     * 部署流程文件
     * @param file 流程定义文件
     * @param bpmnLabel 流程定义名称
     * @param bpmnType 流程定义类型
     * @param info 备注
     */
    @Override
    @Transactional
    public void deploy(MultipartFile file, String bpmnLabel,
                       Integer bpmnType, String info) throws IOException {
        Assert.notNull(file,"文件不能空");
        //1 文件上传：文件格式校验，bpmn文件
        // bus_service_car_package.bpmn
        String originalFilename = file.getOriginalFilename();
        Assert.notNull(originalFilename,"文件名称不能空");
        String suffix=originalFilename.substring(originalFilename.lastIndexOf(".")+1);
        System.out.println(suffix);
        Assert.state("bpmn".equals(suffix),"文件上传格式不对，需要bpmn类型");
        //2 部署
        // 资源名称，文件输入流
        Deployment deploy = repositoryService.createDeployment()
                .name(bpmnLabel)
                .addInputStream(originalFilename, file.getInputStream())
                .deploy();
        // 部署好id
//        deploy.getId();
        // 查询已部署好的信息
        /** 流程名称 */
        ProcessDefinition processDefinition = repositoryService
                .createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        // 发生查询singleResult()
        //3 落库bpmnInfo表
        //processDefinitionKey
        //version
        BusBpmnInfo busBpmnInfo=new BusBpmnInfo();
        busBpmnInfo.setBpmnLabel(bpmnLabel);
        busBpmnInfo.setBpmnType(bpmnType);
        busBpmnInfo.setInfo(info);
        busBpmnInfo.setDeployTime(DateUtils.getNowDate());
        busBpmnInfo.setProcessDefinitionKey(processDefinition.getKey());
        busBpmnInfo.setVersion(new Long(processDefinition.getVersion()));
        busBpmnInfoMapper.insertBusBpmnInfo(busBpmnInfo);
    }

    /**
     *  目标：bus_service_car_package.bpmn byte数组
     *  生成xml或者图片
     * 查看流程定义资源
     * @param type 生成类型
     * @param id
     */
    @Override
    public InputStream getResource(String type, Long id) {
        Assert.notNull(type,"非法参数");
        // 1 bpmn_info: id---process_definition_key,version
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBusBpmnInfoById(id);
        Assert.notNull(busBpmnInfo,"不存在部署流程文件");
        // 2 re_procdef: process_definition_key,version---deployment_id
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(busBpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(busBpmnInfo.getVersion().intValue())
                .singleResult();
        Assert.notNull(processDefinition,"不存在部署流程文件");
        String deploymentId = processDefinition.getDeploymentId();
        String resourceName = processDefinition.getResourceName();
        // 3 ge_bytearray  byte数组--->deployment_id
        // 直接返回就是xml格式
        if("xml".equals(type.trim())){
            InputStream is = repositoryService.getResourceAsStream(deploymentId, resourceName);
            return is;
        }
        // 图片类型
        DefaultProcessDiagramGenerator generator=new DefaultProcessDiagramGenerator();
        //generateDiagram(bpmn模型,需要高亮节点ID集合,需要高亮连线ID集合)
        // 查看进度的时候
        // BpmnModel bpmnModel, 流程定义对象
        // List<String> highLightedActivities,需要高亮节点ID集合
        // List<String> highLightedFlows,需要高亮连线ID集合
        // String activityFontName, “宋体”
        // String labelFontName, “宋体”
        // String annotationFontName，“宋体”
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        InputStream is = generator.generateDiagram(bpmnModel,
                Collections.EMPTY_LIST,
                Collections.EMPTY_LIST,
                "宋体",
                "宋体",
                "宋体"
        );
        return is;
    }
}
